#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <random>
#include <chrono>
#include <iomanip>
#include <atomic>

using namespace std;
using namespace std::chrono;

const int WINDOW_SIZE = 5;//窗口大小
const int TOTAL_PACKETS = 20;//总包数
const double LOSS_PROBABILITY = 0.3;//丢包概率

mutex cout_mutex;//控制输出
mutex ack_mutex;//控制ACK队列
mutex packet_mutex;//控制包队列
condition_variable ack_cv;//ACK条件变量
condition_variable packet_cv;//包条件变量

atomic<bool> running{true};//控制线程运行

//包结构
struct Packet {
    int seq_num;
    bool acked;
    bool delivered;
    time_point<system_clock> send_time;
};

//窗口状态结构
struct WindowStatus {
    vector<int> sent_acked;//已发送并收到确认
    vector<int> sent_not_acked;//已发送但未收到确认
    vector<int> can_send_not_sent;//允许发送但尚未发送
    vector<int> cannot_send;//不允许发送
    vector<int> acked_delivered;//已发送确认并交付主机
    vector<int> can_receive;//允许接收
    vector<int> cannot_receive;//不允许接收
    int notify_window_size;//通知窗口大小
    int available_window_size;//可用窗口大小
};

queue<Packet> packet_queue;//包队列
queue<int> ack_queue;//ACK队列

//甲方发送线程
void sender_thread(int start_seq)
{
    int next_seq = start_seq;
    vector<Packet> window;
    
    default_random_engine generator(system_clock::now().time_since_epoch().count());
    uniform_real_distribution<double> distribution(0.0, 1.0);
    
    while (next_seq < start_seq + TOTAL_PACKETS && running)
	{
        unique_lock<mutex> plock(packet_mutex);
        
        //如果窗口未满，发送新包
        if (window.size() < WINDOW_SIZE && next_seq < start_seq + TOTAL_PACKETS)
		{
            Packet p{next_seq, false, false, system_clock::now()};
            window.push_back(p);
            
            //模拟丢包
            if (distribution(generator) >= LOSS_PROBABILITY)
			{
                packet_queue.push(p);
                lock_guard<mutex> lock(cout_mutex);
                cout << "Sender: Sent packet " << p.seq_num << endl;
            }
			else
			{
                lock_guard<mutex> lock(cout_mutex);
                cout << "Sender: Packet " << p.seq_num << " lost!" << endl;
            }
            
            next_seq++;
        }
        
        plock.unlock();
        
        //检查ACK
        unique_lock<mutex> alock(ack_mutex);
        if (!ack_queue.empty())
		{
            int ack_seq = ack_queue.front();
            ack_queue.pop();
            alock.unlock();
            
            //从窗口中移除已确认的包
            auto it = window.begin();
            while (it != window.end())
			{
                if (it->seq_num <= ack_seq)
				{
                    it->acked = true;
                    it->delivered = true;
                    it = window.erase(it);
                }
				else ++it;
            }
            
            lock_guard<mutex> lock(cout_mutex);
            cout << "Sender: Received ACK " << ack_seq << endl;
        }
		else alock.unlock();
        
        //超时重传
        for (auto& p : window)
		{
            auto now = system_clock::now();
            if (duration_cast<milliseconds>(now - p.send_time).count() > 2000 && !p.acked)
			{
                //模拟丢包
                if (distribution(generator) >= LOSS_PROBABILITY)
				{
                    packet_queue.push(p);
                    p.send_time = system_clock::now();
                    lock_guard<mutex> lock(cout_mutex);
                    cout << "Sender: Retransmitted packet " << p.seq_num << endl;
                }
				else
				{
                    lock_guard<mutex> lock(cout_mutex);
                    cout << "Sender: Retransmit packet " << p.seq_num << " lost!" << endl;
                }
            }
        }
        
        this_thread::sleep_for(milliseconds(500));
    }
}

//乙方接收线程
void receiver_thread()
{
    int expected_seq = 0;
    
    while (running)
	{
        unique_lock<mutex> plock(packet_mutex);
        if (!packet_queue.empty())
		{
            Packet p = packet_queue.front();
            packet_queue.pop();
            plock.unlock();
            
            if (p.seq_num == expected_seq)
			{
                //正确顺序的包
                lock_guard<mutex> lock(cout_mutex);
                cout << "Receiver: Received packet " << p.seq_num << endl;
                
                expected_seq++;
                
                //发送ACK
                unique_lock<mutex> alock(ack_mutex);
                ack_queue.push(p.seq_num);
                ack_cv.notify_one();
                alock.unlock();
                
                    lock_guard<mutex> lock(cout_mutex);
                    cout << "Receiver: Sent ACK " << p.seq_num << endl;
            }
			else if (p.seq_num > expected_seq)
			{
                //乱序包，缓存并发送最后一个按序到达的ACK
                lock_guard<mutex> lock(cout_mutex);
                cout << "Receiver: Out-of-order packet " << p.seq_num << ", expected " << expected_seq << endl;
                
                unique_lock<mutex> alock(ack_mutex);
                ack_queue.push(expected_seq - 1);
                ack_cv.notify_one();
                alock.unlock();
                
                lock_guard<mutex> lock(cout_mutex);
                cout << "Receiver: Sent duplicate ACK " << expected_seq - 1 << endl;
            }
			else
			{
                //重复包
                {
                    lock_guard<mutex> lock(cout_mutex);
                    cout << "Receiver: Duplicate packet " << p.seq_num << endl;
                }
                
                unique_lock<mutex> alock(ack_mutex);
                ack_queue.push(p.seq_num);
                ack_cv.notify_one();
                alock.unlock();
            }
        }
		else
		{
            plock.unlock();
            this_thread::sleep_for(milliseconds(100));
        }
    }
}

//获取窗口状态
WindowStatus get_window_status(int next_seq, int expected_seq, const vector<Packet>& window)
{
    WindowStatus status;
    
    //计算发送方窗口状态
    int base_seq = window.empty() ? next_seq : window.front().seq_num;
    
    //已发送并收到确认(小于base_seq)
    for (int i = 0; i < base_seq; i++)
	{
        status.sent_acked.push_back(i);
    }
    
    //已发送但未收到确认(窗口中的包)
    for (const auto& p : window)
	{
        status.sent_not_acked.push_back(p.seq_num);
    }
    
    //允许发送但尚未发送(从base_seq + window.size()到next_seq - 1)
    for (int i = base_seq + window.size(); i < next_seq; i++)
	{
        status.can_send_not_sent.push_back(i);
    }
    
    //不允许发送(next_seq及之后)
    for (int i = next_seq; i < next_seq + 5; i++)
	{
        status.cannot_send.push_back(i);
    }
    
    //已发送确认并交付主机(小于expected_seq)
    for (int i = 0; i < expected_seq; i++)
	{
        status.acked_delivered.push_back(i);
    }
    
    //允许接收(expected_seq 到 expected_seq + WINDOW_SIZE - 1)
    for (int i = expected_seq; i < expected_seq + WINDOW_SIZE; i++)
	{
        status.can_receive.push_back(i);
    }
    
    //不允许接收(expected_seq + WINDOW_SIZE 及之后)
    for (int i = expected_seq + WINDOW_SIZE; i < expected_seq + WINDOW_SIZE + 5; i++)
	{
        status.cannot_receive.push_back(i);
    }
    
    //通知窗口大小和可用窗口大小
    status.notify_window_size = WINDOW_SIZE;
    status.available_window_size = WINDOW_SIZE - window.size();
    
    return status;
}

//监控线程，每秒输出窗口状态
void monitor_thread(int start_seq, int* next_seq_ptr, int* expected_seq_ptr, vector<Packet>* window_ptr)
{
    while (running)
	{
        // 获取当前窗口状态
        WindowStatus status = get_window_status(*next_seq_ptr, *expected_seq_ptr, *window_ptr);
        
        //输出窗口状态
            lock_guard<mutex> lock(cout_mutex);
            cout << "\n=== Window Status ===" << endl;
            cout << "Sent and ACKed: ";
            for (int seq : status.sent_acked) cout << seq << " ";
            cout << "\nSent but not ACKed: ";
            for (int seq : status.sent_not_acked) cout << seq << " ";
            cout << "\nCan send but not sent: ";
            for (int seq : status.can_send_not_sent) cout << seq << " ";
            cout << "\nCannot send: ";
            for (int seq : status.cannot_send) cout << seq << " ";
            cout << "\nACKed and delivered: ";
            for (int seq : status.acked_delivered) cout << seq << " ";
            cout << "\nCan receive: ";
            for (int seq : status.can_receive) cout << seq << " ";
            cout << "\nCannot receive: ";
            for (int seq : status.cannot_receive) cout << seq << " ";
            cout << "\nNotify window size: " << status.notify_window_size;
            cout << "\nAvailable window size: " << status.available_window_size << endl;
            cout << "====================\n" << endl;
        
        this_thread::sleep_for(seconds(1));
    }
}

int main()
{
    int start_seq = 0;
    int next_seq = start_seq;
    int expected_seq = 0;
    vector<Packet> window;
    
    //启动发送线程
    thread sender(sender_thread, start_seq);
    
    //启动接收线程
    thread receiver(receiver_thread);
    
    //启动监控线程
    thread monitor(monitor_thread, start_seq, &next_seq, &expected_seq, &window);
    
    //运行一段时间后停止
    this_thread::sleep_for(seconds(15));
    running = false;
    
    sender.join();
    receiver.join();
    monitor.join();
    
    return 0;
}